package io.github.junxworks.qt.modules.stock.controller;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.curator.shaded.com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import io.github.junxworks.ep.core.Result;
import io.github.junxworks.ep.core.orm.annotations.Column;
import io.github.junxworks.ep.core.utils.PageUtils;
import io.github.junxworks.ep.sys.service.EpDataService;
import io.github.junxworks.junx.core.util.NumberUtils;
import io.github.junxworks.junx.core.util.ObjectUtils;
import io.github.junxworks.qt.modules.bi.vo.Series;
import io.github.junxworks.qt.modules.stock.dto.TsQueryCondition;
import io.github.junxworks.qt.modules.stock.service.StockService;
import io.github.junxworks.qt.modules.stock.vo.DStockHoldernumberVo;
import io.github.junxworks.qt.modules.stock.vo.DStockToptenHoldersVo;
import io.github.junxworks.qt.modules.tushare.entity.DStockTradeDailyBasic;
import io.github.junxworks.qt.modules.tushare.service.TradeInfoService;
import net.vidageek.mirror.list.dsl.MirrorList;

@RestController
@RequestMapping("/stock")
public class StockController {

	@Autowired
	private EpDataService dataService;

	@Autowired
	private StockService stockService;

	@Autowired
	private TradeInfoService tradeInfoService;

	@GetMapping("/company")
	public Result company(TsQueryCondition condition) {
		return Result.ok(stockService.queryStockCompany(condition.getTsCode()));
	}

	@GetMapping("/single/indicators")
	public Result indicators(@RequestParam Map<String, String> params) throws Exception {
		if (params.get("unit") == null) {
			params.put("unit", "1");
		}
		List<Map<String, Object>> tds = dataService.getDataBySQLUid(params.get("sqlid"), params);
		List<String> category = Lists.newArrayList();
		List<Object> data = Lists.newArrayList();
		for (Map<String, Object> m : tds) {
			category.add(String.valueOf(m.get("category")));
			data.add(m.get("data"));
		}
		if (!category.isEmpty() && "bi_stock_indicators".equalsIgnoreCase(params.get("sqlid")) && "d_stock_mv".equalsIgnoreCase(params.get("tableName"))) {
			String endDate = params.get("endDate");
			String recentTradeDate = tradeInfoService.queryRecentTradeDate(endDate);//当前最新交易日
			if (!recentTradeDate.equals(category.get(category.size() - 1)) && Integer.valueOf(recentTradeDate) > Integer.valueOf(category.get(category.size() - 1))) {
				//补齐当前最新数据
				DStockTradeDailyBasic tradeBasic = tradeInfoService.queryTradeDailyBasicByCodeAndDate(params.get("stock"), recentTradeDate);
				if (tradeBasic == null) {
					recentTradeDate = tradeInfoService.queryTradeCalByOffset(recentTradeDate, -1);
					tradeBasic = tradeInfoService.queryTradeDailyBasicByCodeAndDate(params.get("stock"), recentTradeDate);
				}
				String field = params.get("indicatorField");
				MirrorList<Field> fs = ObjectUtils.mirror().on(DStockTradeDailyBasic.class).reflectAll().fields();
				for (Field f : fs) {
					Column c = f.getAnnotation(Column.class);
					if (c != null && field.equals(c.name())) {
						Object value = ObjectUtils.mirror().on(tradeBasic).get().field(f);
						if (value != null && !value.equals(Float.valueOf(Integer.MIN_VALUE))) {
							Object unit = params.getOrDefault("unit", "1");
							data.add(NumberUtils.devide(value, unit, 2));
							category.add(recentTradeDate);
						}
						break;
					}
				}
			}
		}
		Result res = Result.ok();
		res.addAttribute("category", category);
		res.addAttribute("data", data);
		return res;
	}

	@GetMapping("/single/holdernumber")
	public Result holdernumber(TsQueryCondition condition) throws Exception {
		List<DStockHoldernumberVo> d = stockService.queryHoldernumber(condition);
		List<String> category = Lists.newArrayList();
		List<Object> data = Lists.newArrayList();
		d.forEach(_d -> {
			category.add(_d.getEndDate());
			data.add(_d.getHolderNum());
		});
		Result res = Result.ok();
		res.addAttribute("category", category);
		res.addAttribute("data", data);
		return res;
	}

	@GetMapping("/single/forecast")
	public Result forecast(TsQueryCondition condition) throws Exception {
		PageUtils.setPage(condition);
		return Result.ok(new PageInfo<>(stockService.queryStockForecast(condition)));
	}

	@GetMapping("/single/mainbz")
	public Result mainbz(TsQueryCondition condition) throws Exception {
		PageUtils.setPage(condition);
		return Result.ok(new PageInfo<>(stockService.queryMainBz(condition)));
	}

	@GetMapping("/single/blocktrade")
	public Result blockTrade(TsQueryCondition condition) throws Exception {
		PageUtils.setPage(condition);
		return Result.ok(new PageInfo<>(stockService.queryBlockTrade(condition)));
	}

	@GetMapping("/single/floatholders")
	public Result floatholders(TsQueryCondition condition) throws Exception {
		PageUtils.setPage(condition);
		return Result.ok(new PageInfo<>(stockService.queryFloatHolders(condition)));
	}

	@GetMapping("/single/repurchase")
	public Result repurchase(TsQueryCondition condition) throws Exception {
		PageUtils.setPage(condition);
		return Result.ok(new PageInfo<>(stockService.queryRepurchase(condition)));
	}

	@GetMapping("/single/holdertrade")
	public Result holdertrade(TsQueryCondition condition) throws Exception {
		PageUtils.setPage(condition);
		return Result.ok(new PageInfo<>(stockService.queryHoldertrade(condition)));
	}

	@GetMapping("/single/holders")
	public Result holders(TsQueryCondition condition) throws Exception {
		Result res = Result.ok();
		List<DStockToptenHoldersVo> hoders = stockService.queryHolders(condition);
		Set<String> legendData = Sets.newHashSet();
		List<String> xAxisData = Lists.newArrayList();
		Map<String, Series> series = Maps.newHashMap();
		Map<String, Object> values = Maps.newHashMap();
		List<Series> ss = Lists.newArrayList();
		hoders.stream().forEach(v -> {
			String holderName = v.getHolderName();
			legendData.add(holderName);
			if (!xAxisData.contains(v.getEndDate())) {
				xAxisData.add(v.getEndDate());
			}
			values.put(holderName + "-" + v.getEndDate(), v.getHoldRatio());
		});
		legendData.forEach(l -> {
			xAxisData.forEach(d -> {
				Series s = series.get(l);
				if (s == null) {
					s = new Series();
					s.setName(l);
					s.setStack("1");
					s.setType("bar");
					series.put(l, s);
					ss.add(s);
				}
				Object v = values.get(l + "-" + d);
				s.addData(v == null ? 0 : v);
			});
		});
		res.addAttribute("legendData", legendData);
		res.addAttribute("xAxisData", xAxisData);
		res.addAttribute("series", ss);
		return res;
	}
}
